package com.bestcem.xm.award.service.impl;

import com.bestcem.xm.award.constant.Constants;
import com.bestcem.xm.award.entity.pojo.AwardAwardDO;
import com.bestcem.xm.award.entity.pojo.AwardRecordDO;
import com.bestcem.xm.award.entity.pojo.AwardWinDO;
import com.bestcem.xm.award.enums.AwardIssueTypeEnum;
import com.bestcem.xm.award.enums.AwardTypeEnum;
import com.bestcem.xm.award.service.bo.award.AwardAwardBO;
import com.bestcem.xm.award.service.bo.award.WinDataBO;
import com.bestcem.xm.award.util.DrawUtil;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

import static com.bestcem.xm.award.constant.Constants.DrawAwardParamsRule.*;
import static com.bestcem.xm.award.enums.AwardTypeEnum.NEW_DRAW;

/**
 * 新抽奖服务
 *
 * @author hang.li <hang.li@idiaoyan.com>
 * @version v1.0
 * @date 2021/8/18 17:48
 */
@Slf4j
@Service(value = "DrawNewAwardServiceImpl")
public class DrawNewAwardServiceImpl extends DrawAwardServiceImpl {

    /**
     * 获取奖励类型
     *
     * @return 新抽奖类型
     */
    @Override
    public AwardTypeEnum getAwardTypeEnum() {
        return NEW_DRAW;
    }

    @Override
    protected void doDrawLimitCheckMethod(AwardAwardDO award, AwardRecordDO.Win win, AwardAwardDO.Award awardDetail) {
        if (AwardIssueTypeEnum.CODE.getIndex() == awardDetail.getMethod()) {
            win.setMethod(AwardIssueTypeEnum.CODE.getIndex());
            if (StringUtils.isNotBlank(awardDetail.getPrefix())) {
                // 系统生成兑奖码
                String prefix = awardDetail.getPrefix();
                win.setCode(DrawUtil.generateCode(prefix, 14));
            } else {
                // 使用自定义兑奖码
                AwardWinDO awardWin = winDao.findAndUpdateByIdAndNameAndUsed(award.getId(), win.getName(), false);
                win.setCode(awardWin.getCode());
            }
        } else {
            win.setMethod(AwardIssueTypeEnum.ADDR.getIndex());
        }
    }

    @Override
    protected void createPoolUnlimitedCheckMethod(AwardAwardDO award, AwardRecordDO.Win win, AwardAwardDO.Award awardDetail) {
        if (AwardIssueTypeEnum.CODE.getIndex() == awardDetail.getMethod()) {
            win.setMethod(AwardIssueTypeEnum.CODE.getIndex());
            String prefix = awardDetail.getPrefix();
            win.setCode(DrawUtil.generateCode(prefix, 14));
        } else {
            win.setMethod(AwardIssueTypeEnum.ADDR.getIndex());
        }
    }

    @Override
    public ServiceResult<String> independentCheckAward(AwardAwardBO awardAward) {
        ServiceResult<String> result = checkAward(awardAward);
        if (!result.isSuccess()) {
            return ServiceResult.fail(result.getMsg());
        }
        Optional<AwardAwardBO> optional = Optional.of(awardAward);
        List<AwardAwardBO.Award> awardList = awardAward.getAwards();
        if (awardList.stream().anyMatch(award -> award.getProb() == null || award.getProb().compareTo(BigDecimal.ZERO) <= 0)) {
            return ServiceResult.fail("奖项概率不能小于等于0！");
        }
        int totalCount = optional.map(AwardAwardBO::getBasic).map(AwardAwardBO.Basic::getTotalCount).orElse(0);
        if (totalCount > 0) {
            if (awardList.stream().anyMatch(award -> award.getNum() == null || award.getNum() <= 0)) {
                return ServiceResult.fail("奖项数量缺失！");
            }
            int sum = awardList.stream().map(AwardAwardBO.Award::getNum).reduce(0, Integer::sum);
            if (sum > totalCount) {
                return ServiceResult.fail("所有奖项数量的和必须小于限制抽奖次数");
            }
            for (AwardAwardBO.Award award : awardList) {
                award.setProb(BigDecimal.valueOf((((double) (award.getNum() * 100)) / (double) totalCount)));
            }
        } else {
            awardAward.getBasic().setTotalCount(null);
            BigDecimal sumProb = BigDecimal.ZERO;
            for (AwardAwardBO.Award award : awardList) {
                sumProb = sumProb.add(award.getProb());
            }
            if (sumProb.compareTo(new BigDecimal(Constants.LONG_HUNDRED)) > 0) {
                return ServiceResult.fail("概率和不可大于100%");
            }
            for (AwardAwardBO.Award award : awardList) {
                if (award.getMethod() == AwardIssueTypeEnum.CODE.getIndex()) {
                    if (StringUtils.isBlank(award.getPrefix())) {
                        return ServiceResult.fail("兑奖码前缀缺失");
                    }
                }
            }
        }
        String sms = optional.map(AwardAwardBO::getIssue).map(AwardAwardBO.Issue::getSms).orElse(Constants.BLANK);
        if (sms.length() > SMS_CONTENT_MAX_LENGTH) {
            return ServiceResult.fail(SMS_CONTENT_LENGTH_ERROR_MESSAGE);
        }
        String tip = optional.map(AwardAwardBO::getIssue).map(AwardAwardBO.Issue::getTip).orElse(Constants.BLANK);
        if (tip.length() > AWARD_TIP_MAX_LENGTH) {
            return ServiceResult.fail(AWARD_TIP_LENGTH_ERROR_MESSAGE);
        }
        awardAward.setPage(null);
        return ServiceResult.success();
    }

    @Override
    protected ServiceResult<String> saveWins(AwardAwardBO awardAward, WinDataBO winData) {
        if (Objects.nonNull(awardAward.getBasic().getTotalCount()) && awardAward.getBasic().getTotalCount() > 0) {
            if (checkCode(awardAward.getAwards())) {
                List<AwardAwardBO.Award> awards = awardAward.getAwards();
                if (Objects.isNull(winData)) {
                    return ServiceResult.fail("手动上传兑奖码数据缺失");
                }
                // 解析数据
                List<AwardWinDO> winList = convertWinsList(awardAward.getId(), winData.getWins());
                Map<String, Integer> map = new HashMap<>(Constants.SIXTEEN);
                for (AwardWinDO awardWin : winList) {
                    String name = awardWin.getName();
                    map.put(name, map.getOrDefault(name, 0) + 1);
                }
                for (AwardAwardBO.Award award : awards) {
                    if (award.getMethod() == AwardIssueTypeEnum.CODE.getIndex() && StringUtils.isBlank(award.getPrefix())) {
                        if (map.getOrDefault(award.getName(), 0).intValue() != award.getNum()) {
                            return ServiceResult.fail("奖项: " + award.getName() + ",兑奖码数量与奖项数量不匹配");
                        }
                    }
                }
                // 删除老数据
                awardWinDao.deleteByAwardId(awardAward.getId());
                // 插入兑奖码数据
                awardWinDao.insertMany(winList);
            }
        }
        return ServiceResult.success();
    }

    /**
     * 判断是否需要上传兑奖码
     *
     * @param awardList 奖项列表
     * @return boolean
     */
    public boolean checkCode(List<AwardAwardBO.Award> awardList) {
        if (!CollectionUtils.isEmpty(awardList)) {
            for (AwardAwardBO.Award award : awardList) {
                if (award.getMethod() == AwardIssueTypeEnum.CODE.getIndex() && StringUtils.isBlank(award.getPrefix())) {
                    return true;
                }
            }
        }
        return false;
    }
}